From 556c27d4834cd509c77883858b68ba43b0e0d76a Mon Sep 17 00:00:00 2001 From: "kaf24@viper.(none)" Date: Sun, 3 Apr 2005 11:22:11 +0000 Subject: [PATCH] bitkeeper revision 1.1236.1.206 (424fd1e3OF1dIgDtN9JonRnCv2YHrQ) Clean up symtab loading in elf loader. Signed-off-by: Keir Fraser --- tools/libxc/xc_linux_build.c | 29 +++++---- tools/libxc/xc_vmx_build.c | 117 +---------------------------------- xen/arch/x86/domain_build.c | 13 ++-- xen/common/elf.c | 110 ++++++++++++++++---------------- xen/include/xen/elf.h | 5 +- xen/include/xen/sched.h | 9 ++- 6 files changed, 83 insertions(+), 200 deletions(-) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 469861b786..d4b28de06e 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -22,8 +22,7 @@ struct domain_setup_info unsigned long v_kernend; unsigned long v_kernentry; - unsigned int load_bsd_symtab; - + unsigned int load_symtab; unsigned long symtab_addr; unsigned long symtab_len; }; @@ -34,7 +33,7 @@ parseelfimage( static int loadelfimage( char *elfbase, int xch, u32 dom, unsigned long *parray, - unsigned long vstart); + struct domain_setup_info *dsi); static int loadelfsymtab( char *elfbase, int xch, u32 dom, unsigned long *parray, @@ -87,9 +86,6 @@ static int setup_guest(int xc_handle, if ( rc != 0 ) goto error_out; - if (dsi.load_bsd_symtab) - loadelfsymtab(image, xc_handle, dom, NULL, &dsi); - if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 ) { PERROR("Guest OS must load to a page boundary.\n"); @@ -160,10 +156,7 @@ static int setup_guest(int xc_handle, goto error_out; } - loadelfimage(image, xc_handle, dom, page_array, dsi.v_start); - - if (dsi.load_bsd_symtab) - loadelfsymtab(image, xc_handle, dom, page_array, &dsi); + loadelfimage(image, xc_handle, dom, page_array, &dsi); /* Load the initial ramdisk image. */ if ( initrd_len != 0 ) @@ -581,21 +574,22 @@ static int parseelfimage(char *elfbase, dsi->v_start = strtoul(p+10, &p, 0); if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL ) - dsi->load_bsd_symtab = 1; + dsi->load_symtab = 1; dsi->v_kernstart = kernstart; dsi->v_kernend = kernend; dsi->v_kernentry = ehdr->e_entry; - dsi->v_end = dsi->v_kernend; + loadelfsymtab(elfbase, 0, 0, NULL, dsi); + return 0; } static int loadelfimage( char *elfbase, int xch, u32 dom, unsigned long *parray, - unsigned long vstart) + struct domain_setup_info *dsi) { Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase; Elf_Phdr *phdr; @@ -612,7 +606,7 @@ loadelfimage( for ( done = 0; done < phdr->p_filesz; done += chunksz ) { - pa = (phdr->p_paddr + done) - vstart; + pa = (phdr->p_paddr + done) - dsi->v_start; va = xc_map_foreign_range( xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]); chunksz = phdr->p_filesz - done; @@ -625,7 +619,7 @@ loadelfimage( for ( ; done < phdr->p_memsz; done += chunksz ) { - pa = (phdr->p_paddr + done) - vstart; + pa = (phdr->p_paddr + done) - dsi->v_start; va = xc_map_foreign_range( xch, dom, PAGE_SIZE, PROT_WRITE, parray[pa>>PAGE_SHIFT]); chunksz = phdr->p_memsz - done; @@ -636,6 +630,8 @@ loadelfimage( } } + loadelfsymtab(elfbase, xch, dom, parray, dsi); + return 0; } @@ -652,6 +648,9 @@ loadelfsymtab( char *p; int h, i; + if ( !dsi->load_symtab ) + return 0; + p = malloc(sizeof(int) + sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr)); if (p == NULL) diff --git a/tools/libxc/xc_vmx_build.c b/tools/libxc/xc_vmx_build.c index ed9868e9f0..dcd4f574f5 100644 --- a/tools/libxc/xc_vmx_build.c +++ b/tools/libxc/xc_vmx_build.c @@ -26,11 +26,6 @@ struct domain_setup_info unsigned long v_kernstart; unsigned long v_kernend; unsigned long v_kernentry; - - unsigned int load_bsd_symtab; - - unsigned long symtab_addr; - unsigned long symtab_len; }; static int @@ -40,10 +35,6 @@ static int loadelfimage( char *elfbase, int xch, u32 dom, unsigned long *parray, unsigned long vstart); -static int -loadelfsymtab( - char *elfbase, int xch, u32 dom, unsigned long *parray, - struct domain_setup_info *dsi); static void build_e820map(struct mem_map *mem_mapp, unsigned long mem_size) { @@ -193,13 +184,9 @@ static int setup_guest(int xc_handle, memset(&dsi, 0, sizeof(struct domain_setup_info)); - rc = parseelfimage(image, image_size, &dsi); - if ( rc != 0 ) + if ( (rc = parseelfimage(image, image_size, &dsi)) != 0 ) goto error_out; - if (dsi.load_bsd_symtab) - loadelfsymtab(image, xc_handle, dom, NULL, &dsi); - if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 ) { PERROR("Guest OS must load to a page boundary.\n"); @@ -269,9 +256,6 @@ static int setup_guest(int xc_handle, loadelfimage(image, xc_handle, dom, page_array, dsi.v_start); - if (dsi.load_bsd_symtab) - loadelfsymtab(image, xc_handle, dom, page_array, &dsi); - /* Load the initial ramdisk image. */ if ( initrd_len != 0 ) { @@ -708,7 +692,6 @@ static int parseelfimage(char *elfbase, } dsi->v_start = 0x00000000; - dsi->load_bsd_symtab = 0; dsi->v_kernstart = kernstart - LINUX_PAGE_OFFSET; dsi->v_kernend = kernend - LINUX_PAGE_OFFSET; @@ -769,101 +752,3 @@ loadelfimage( return 0; } - - -#define ELFROUND (ELFSIZE / 8) - -static int -loadelfsymtab( - char *elfbase, int xch, u32 dom, unsigned long *parray, - struct domain_setup_info *dsi) -{ - Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr; - Elf_Shdr *shdr; - unsigned long maxva, symva; - char *p; - int h, i; - - p = malloc(sizeof(int) + sizeof(Elf_Ehdr) + - ehdr->e_shnum * sizeof(Elf_Shdr)); - if (p == NULL) - return 0; - - maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1); - symva = maxva; - maxva += sizeof(int); - dsi->symtab_addr = maxva; - dsi->symtab_len = 0; - maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr); - maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1); - - shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr)); - memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr)); - - for ( h = 0; h < ehdr->e_shnum; h++ ) - { - if ( shdr[h].sh_type == SHT_STRTAB ) - { - /* Look for a strtab @i linked to symtab @h. */ - for ( i = 0; i < ehdr->e_shnum; i++ ) - if ( (shdr[i].sh_type == SHT_SYMTAB) && - (shdr[i].sh_link == h) ) - break; - /* Skip symtab @h if we found no corresponding strtab @i. */ - if ( i == ehdr->e_shnum ) - { - shdr[h].sh_offset = 0; - continue; - } - } - - if ( (shdr[h].sh_type == SHT_STRTAB) || - (shdr[h].sh_type == SHT_SYMTAB) ) - { - if ( parray != NULL ) - xc_map_memcpy(maxva, elfbase + shdr[h].sh_offset, shdr[h].sh_size, - xch, dom, parray, dsi->v_start); - - /* Mangled to be based on ELF header location. */ - shdr[h].sh_offset = maxva - dsi->symtab_addr; - - dsi->symtab_len += shdr[h].sh_size; - maxva += shdr[h].sh_size; - maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1); - } - - shdr[h].sh_name = 0; /* Name is NULL. */ - } - - if ( dsi->symtab_len == 0 ) - { - dsi->symtab_addr = 0; - goto out; - } - - if ( parray != NULL ) - { - *(int *)p = maxva - dsi->symtab_addr; - sym_ehdr = (Elf_Ehdr *)(p + sizeof(int)); - memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr)); - sym_ehdr->e_phoff = 0; - sym_ehdr->e_shoff = sizeof(Elf_Ehdr); - sym_ehdr->e_phentsize = 0; - sym_ehdr->e_phnum = 0; - sym_ehdr->e_shstrndx = SHN_UNDEF; - - /* Copy total length, crafted ELF header and section header table */ - xc_map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) + - ehdr->e_shnum * sizeof(Elf_Shdr), xch, dom, parray, - dsi->v_start); - } - - dsi->symtab_len = maxva - dsi->symtab_addr; - dsi->v_end = round_pgup(maxva); - - out: - if ( p != NULL ) - free(p); - - return 0; -} diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index d896df6ad7..b7c8156dfd 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -111,6 +111,8 @@ int construct_dom0(struct domain *d, BUG(); memset(&dsi, 0, sizeof(struct domain_setup_info)); + dsi.image_addr = (unsigned long)image_start; + dsi.image_len = image_len; printk("*** LOADING DOMAIN 0 ***\n"); @@ -125,13 +127,9 @@ int construct_dom0(struct domain *d, alloc_start = page_to_phys(page); alloc_end = alloc_start + (d->tot_pages << PAGE_SHIFT); - rc = parseelfimage(image_start, image_len, &dsi); - if ( rc != 0 ) + if ( (rc = parseelfimage(&dsi)) != 0 ) return rc; - if (dsi.load_bsd_symtab) - loadelfsymtab(image_start, 0, &dsi); - /* Align load address to 4MB boundary. */ dsi.v_start &= ~((1UL<<22)-1); @@ -424,10 +422,7 @@ int construct_dom0(struct domain *d, write_ptbase(ed); /* Copy the OS image and free temporary buffer. */ - (void)loadelfimage(image_start); - - if (dsi.load_bsd_symtab) - loadelfsymtab(image_start, 1, &dsi); + (void)loadelfimage(&dsi); init_domheap_pages( _image_start, (_image_start+image_len+PAGE_SIZE-1) & PAGE_MASK); diff --git a/xen/common/elf.c b/xen/common/elf.c index 1302acfdea..98f9565e2d 100644 --- a/xen/common/elf.c +++ b/xen/common/elf.c @@ -17,33 +17,33 @@ #define FORCE_XENELF_IMAGE 0 #endif +static void loadelfsymtab(struct domain_setup_info *dsi, int doload); static inline int is_loadable_phdr(Elf_Phdr *phdr) { return ((phdr->p_type == PT_LOAD) && ((phdr->p_flags & (PF_W|PF_X)) != 0)); } -int parseelfimage(char *elfbase, - unsigned long elfsize, - struct domain_setup_info *dsi) +int parseelfimage(struct domain_setup_info *dsi) { - Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase; + Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr; Elf_Phdr *phdr; Elf_Shdr *shdr; unsigned long kernstart = ~0UL, kernend=0UL; char *shstrtab, *guestinfo=NULL, *p; + char *elfbase = (char *)dsi->image_addr; int h; if ( !elf_sanity_check(ehdr) ) return -EINVAL; - if ( (ehdr->e_phoff + (ehdr->e_phnum * ehdr->e_phentsize)) > elfsize ) + if ( (ehdr->e_phoff + (ehdr->e_phnum*ehdr->e_phentsize)) > dsi->image_len ) { printk("ELF program headers extend beyond end of image.\n"); return -EINVAL; } - if ( (ehdr->e_shoff + (ehdr->e_shnum * ehdr->e_shentsize)) > elfsize ) + if ( (ehdr->e_shoff + (ehdr->e_shnum*ehdr->e_shentsize)) > dsi->image_len ) { printk("ELF section headers extend beyond end of image.\n"); return -EINVAL; @@ -120,22 +120,23 @@ int parseelfimage(char *elfbase, dsi->v_start = simple_strtoul(p+10, &p, 0); if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL ) - dsi->load_bsd_symtab = 1; - + dsi->load_symtab = 1; } dsi->v_kernstart = kernstart; dsi->v_kernend = kernend; dsi->v_kernentry = ehdr->e_entry; - dsi->v_end = dsi->v_kernend; + loadelfsymtab(dsi, 0); + return 0; } -int loadelfimage(char *elfbase) +int loadelfimage(struct domain_setup_info *dsi) { - Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase; + char *elfbase = (char *)dsi->image_addr; + Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr; Elf_Phdr *phdr; int h; @@ -152,19 +153,24 @@ int loadelfimage(char *elfbase) phdr->p_memsz - phdr->p_filesz); } + loadelfsymtab(dsi, 1); + return 0; } #define ELFROUND (ELFSIZE / 8) -int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi) +static void loadelfsymtab(struct domain_setup_info *dsi, int doload) { - Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr; + Elf_Ehdr *ehdr = (Elf_Ehdr *)dsi->image_addr, *sym_ehdr; Elf_Shdr *shdr; unsigned long maxva, symva; - char *p; + char *p, *elfbase = (char *)dsi->image_addr; int h, i; + if ( !dsi->load_symtab ) + return; + maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1); symva = maxva; maxva += sizeof(int); @@ -172,14 +178,16 @@ int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi) dsi->symtab_len = 0; maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr); maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1); - if (doload) { - p = (void *)symva; - - shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr)); - memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr)); - } else { - shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff); - p = NULL; /* XXX: gcc */ + if ( doload ) + { + p = (void *)symva; + shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr)); + memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum*sizeof(Elf_Shdr)); + } + else + { + p = NULL; + shdr = (Elf_Shdr *)(elfbase + ehdr->e_shoff); } for ( h = 0; h < ehdr->e_shnum; h++ ) @@ -194,9 +202,9 @@ int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi) /* Skip symtab @h if we found no corresponding strtab @i. */ if ( i == ehdr->e_shnum ) { - if (doload) { - shdr[h].sh_offset = 0; - } + if (doload) { + shdr[h].sh_offset = 0; + } continue; } } @@ -204,49 +212,43 @@ int loadelfsymtab(char *elfbase, int doload, struct domain_setup_info *dsi) if ( (shdr[h].sh_type == SHT_STRTAB) || (shdr[h].sh_type == SHT_SYMTAB) ) { - if (doload) { - memcpy((void *)maxva, elfbase + shdr[h].sh_offset, - shdr[h].sh_size); + if (doload) { + memcpy((void *)maxva, elfbase + shdr[h].sh_offset, + shdr[h].sh_size); - /* Mangled to be based on ELF header location. */ - shdr[h].sh_offset = maxva - dsi->symtab_addr; + /* Mangled to be based on ELF header location. */ + shdr[h].sh_offset = maxva - dsi->symtab_addr; - } - dsi->symtab_len += shdr[h].sh_size; - maxva += shdr[h].sh_size; - maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1); + } + dsi->symtab_len += shdr[h].sh_size; + maxva += shdr[h].sh_size; + maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1); } - if (doload) { - shdr[h].sh_name = 0; /* Name is NULL. */ - } + if ( doload ) + shdr[h].sh_name = 0; /* Name is NULL. */ } if ( dsi->symtab_len == 0 ) { dsi->symtab_addr = 0; - goto out; + return; } - if (doload) { - *(int *)p = maxva - dsi->symtab_addr; - sym_ehdr = (Elf_Ehdr *)(p + sizeof(int)); - memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr)); - sym_ehdr->e_phoff = 0; - sym_ehdr->e_shoff = sizeof(Elf_Ehdr); - sym_ehdr->e_phentsize = 0; - sym_ehdr->e_phnum = 0; - sym_ehdr->e_shstrndx = SHN_UNDEF; + if ( doload ) + { + *(int *)p = maxva - dsi->symtab_addr; + sym_ehdr = (Elf_Ehdr *)(p + sizeof(int)); + memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr)); + sym_ehdr->e_phoff = 0; + sym_ehdr->e_shoff = sizeof(Elf_Ehdr); + sym_ehdr->e_phentsize = 0; + sym_ehdr->e_phnum = 0; + sym_ehdr->e_shstrndx = SHN_UNDEF; } -#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) /* XXX */ - dsi->symtab_len = maxva - dsi->symtab_addr; - dsi->v_end = round_pgup(maxva); - - out: - - return 0; + dsi->v_end = maxva; } /* diff --git a/xen/include/xen/elf.h b/xen/include/xen/elf.h index 0b98390ed5..1d2ac6919a 100644 --- a/xen/include/xen/elf.h +++ b/xen/include/xen/elf.h @@ -526,9 +526,8 @@ typedef struct { #endif struct domain_setup_info; -extern int loadelfimage(char *); -extern int loadelfsymtab(char *, int, struct domain_setup_info *); -extern int parseelfimage(char *, unsigned long, struct domain_setup_info *); +extern int loadelfimage(struct domain_setup_info *); +extern int parseelfimage(struct domain_setup_info *); #ifdef Elf_Ehdr extern int elf_sanity_check(Elf_Ehdr *ehdr); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index ac783669d1..2352a82c09 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -151,14 +151,17 @@ struct domain struct domain_setup_info { + /* Initialised by caller. */ + unsigned long image_addr; + unsigned long image_len; + /* Initialised by loader: Public. */ unsigned long v_start; unsigned long v_end; unsigned long v_kernstart; unsigned long v_kernend; unsigned long v_kernentry; - - unsigned int load_bsd_symtab; - + /* Initialised by loader: Private. */ + unsigned int load_symtab; unsigned long symtab_addr; unsigned long symtab_len; }; -- 2.30.2